[slug].vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <script lang='ts' setup>
  2. import { ConstKeys } from '~/enums/const-enums'
  3. import { Api } from '@/api/model/url'
  4. import { useCommonStore } from '@/stores/modules/common'
  5. const route = useRoute()
  6. const detail = ref<any>({})
  7. const tabValue = ref('blog')
  8. const isHasCatalogue = ref(true)
  9. const options = ref([
  10. {
  11. label: 'Read Blog',
  12. value: 'blog',
  13. },
  14. {
  15. label: 'Preview Catalog',
  16. value: 'catalog',
  17. },
  18. ])
  19. const slug = route.params.slug
  20. const { data, pending, error, refresh } = await useAsyncData(
  21. 'blog-detail',
  22. () =>
  23. $fetch(`${ConstKeys.DOMAINDEV}${Api.BlogDetail}`, { params: { slug } }),
  24. )
  25. const seoData = data.value?.result
  26. // 把createTime和updateTime转换为ISO格式
  27. if (seoData?.createTime)
  28. seoData.createTime = new Date(seoData.createTime).toISOString()
  29. if (seoData?.updateTime)
  30. seoData.updateTime = new Date(seoData.updateTime).toISOString()
  31. if (!seoData?.relatedCatalogue)
  32. isHasCatalogue.value = false
  33. detail.value = seoData
  34. useHead({
  35. title: detail.value?.metaTitle,
  36. meta: [
  37. {
  38. name: 'description',
  39. content: detail.value?.metaDescribe,
  40. },
  41. {
  42. property: 'og:title',
  43. content: detail.value?.metaTitle,
  44. },
  45. {
  46. property: 'og:description',
  47. content: detail.value?.metaDescribe,
  48. },
  49. {
  50. property: 'og:image',
  51. content: detail.value?.thumbnailUrl,
  52. },
  53. {
  54. property: 'og:url',
  55. content: `${ConstKeys.DOMAINPRO}/blog/${slug}`,
  56. },
  57. {
  58. property: 'og:type',
  59. content: 'website',
  60. },
  61. {
  62. property: 'twitter:title',
  63. content: detail.value?.metaTitle,
  64. },
  65. {
  66. property: 'twitter:description',
  67. content: detail.value?.metaDescribe,
  68. },
  69. {
  70. property: 'twitter:site',
  71. content: `${ConstKeys.DOMAINPRO}/blog/${slug}`,
  72. },
  73. {
  74. property: 'twitter:image',
  75. content: detail.value?.thumbnailUrl,
  76. },
  77. {
  78. property: 'twitter:card',
  79. content: 'summary_large_image',
  80. },
  81. ],
  82. script: [
  83. // JSON-LD
  84. {
  85. type: 'application/ld+json',
  86. children: JSON.stringify({
  87. datePublished: detail.value?.createTime,
  88. dateModified: detail.value?.updateTime,
  89. }),
  90. },
  91. ],
  92. link: [
  93. {
  94. rel: 'canonical',
  95. href: `${ConstKeys.DOMAINPRO}/blog/${slug}`,
  96. },
  97. ],
  98. })
  99. const { openLoginAndDownloadModal } = useLoginAndDownLoadModal()
  100. async function clickLoginAndDownload(item: any) {
  101. try {
  102. const commonStore = useCommonStore()
  103. commonStore.setDownloadCatalog(item)
  104. const { status } = await openLoginAndDownloadModal()
  105. if (status)
  106. location.reload()
  107. }
  108. catch (error) {
  109. console.log(error)
  110. }
  111. }
  112. </script>
  113. <template>
  114. <div class="blog-detail">
  115. <div class="bg-#F3F4FB ">
  116. <div class="pt-175px pb-110px w-1200-auto flex px-60px">
  117. <img :src="detail?.thumbnailUrl" :alt="detail?.thumbnailAlt" srcset="" class="w-410px h-256px b-rd-10px object-cover mr-40px">
  118. <div class="flex-1 text-left">
  119. <div class="b-rd-400px left-10px text-center w-138px h-32px lh-32px bg-#fff/50 backdrop-blur-20px b-1px b-solid b-#fff/60 text-#9B6CFF text-14px mb-20px">
  120. {{ detail.category_dictText }}
  121. </div>
  122. <h1
  123. class="!mb-20px fw-800 text-40px ls-2 text-#333 line-clamp-2 lh-50px custom-title-font"
  124. >
  125. {{ detail.contentTitle }}
  126. </h1>
  127. <div class="text-16px text-#999 lh-24px">
  128. {{ detail.contentSubhead }}
  129. </div>
  130. </div>
  131. </div>
  132. </div>
  133. <div class="w-1200-auto flex pt-30px">
  134. <div class="w-840px mr-60px">
  135. <div v-if="isHasCatalogue">
  136. <el-segmented v-model="tabValue" :options="options">
  137. <template #default="scope">
  138. <div>
  139. <div>{{ scope.item.label }}</div>
  140. </div>
  141. </template>
  142. </el-segmented>
  143. </div>
  144. <div v-show="tabValue === 'blog'" class="mt-30px content-detail custom-html" v-html="detail.content" />
  145. <div v-show="tabValue === 'catalog'" class="mt-30px">
  146. <iframe
  147. :src="`${detail?.relatedCatalogue?.viewPdf}#view=FitH&toolbar=0&scrollbar=0&navpanes=0`"
  148. allowfullscreen
  149. width="100%"
  150. height="1200px"
  151. style="border: none"
  152. >
  153. 您的浏览器不支持iframe,请使用现代浏览器查看PDF。
  154. </iframe>
  155. </div>
  156. </div>
  157. <div class="flex-1">
  158. <div v-if="isHasCatalogue" class="pos-relative mb-40px">
  159. <img :src="detail?.relatedCatalogue?.coverImg" :alt="detail?.relatedCatalogue?.coverAlt" srcset="" class="w-375px h-240px b-rd-10px object-cover">
  160. <h4
  161. class="!mb-15px !mt-30px fw-800 text-24px text-#333 line-clamp-2"
  162. >
  163. {{ detail?.relatedCatalogue?.title }}
  164. </h4>
  165. <div class="text-14px text-#999 lh-22px line-clamp-2 mb-20px">
  166. {{ detail?.relatedCatalogue?.subhead }}
  167. </div>
  168. <el-button class="!bg-#9B6CFF !text-#fff !b-#9B6CFF !b-rd-380px text-14px fw-bold !h-32px px-20px" @click="clickLoginAndDownload(detail?.relatedCatalogue)">
  169. Download Catalog
  170. </el-button>
  171. </div>
  172. <div class="px-40px pt-34px bg-#E7EAFF b-rd-10px text-center custom-main">
  173. <div class="text-#333 fw-500">
  174. Contact Us to Get
  175. </div>
  176. <div class="text-#333 fw-500 my-6px">
  177. Exclusive Trending Products
  178. </div>
  179. <div class="text-#333 fw-500">
  180. Solutions
  181. </div>
  182. <el-button class="mt-20px !bg-#fff !text-#9B6CFF !w-160px !h-40px !b-0px !b-rd-200px" round>
  183. <nuxt-link :to="{ name: 'contact' }">
  184. Contact Us
  185. </nuxt-link>
  186. </el-button>
  187. </div>
  188. </div>
  189. </div>
  190. <common-block-blog class="!pb-0" />
  191. <AppFooter />
  192. </div>
  193. </template>
  194. <style lang='less' scoped>
  195. .el-segmented {
  196. --el-segmented-item-selected-color: #fff;
  197. --el-segmented-item-selected-bg-color: #9B6CFF;
  198. --el-border-radius-base: 16px;
  199. --el-segmented-bg-color: #F9FAFB;
  200. --el-segmented-color: #333;
  201. width: 100%;
  202. height: 68px;
  203. line-height: 68px;
  204. border-radius: 300px!important;
  205. overflow: hidden;
  206. padding: 0;
  207. ::v-deep .el-segmented__group {
  208. .el-segmented__item-selected,.el-segmented__item{
  209. border-radius: 300px!important;
  210. overflow: hidden;
  211. .el-segmented__item-label{
  212. font-size: 18px;
  213. }
  214. }
  215. }
  216. }
  217. .blog-detail {
  218. ::v-deep(.content-detail) {
  219. font-family: sans-serif;
  220. h2 {
  221. font-size: 1.5em;
  222. font-family: "CustomTitleFont";
  223. margin-top: 1em !important;
  224. margin-bottom: 1em !important;
  225. font-weight: bold;
  226. }
  227. h3 {
  228. display: block;
  229. font-size: 1.17em;
  230. margin-block-start: 1em;
  231. margin-block-end: 1em;
  232. margin-inline-start: 0px;
  233. margin-inline-end: 0px;
  234. margin-bottom: 1em !important;
  235. font-weight: bold;
  236. unicode-bidi: isolate;
  237. font-family: "CustomTitleFont";
  238. }
  239. p {
  240. display: block;
  241. margin-block-start: 1em;
  242. margin-block-end: 1em;
  243. margin-inline-start: 0px;
  244. margin-inline-end: 0px;
  245. unicode-bidi: isolate;
  246. }
  247. ul {
  248. display: block;
  249. list-style-type: disc;
  250. margin-block-start: 1em;
  251. margin-block-end: 1em;
  252. margin-inline-start: 0px;
  253. margin-inline-end: 0px;
  254. padding-inline-start: 40px;
  255. unicode-bidi: isolate;
  256. li {
  257. display: list-item;
  258. text-align: -webkit-match-parent;
  259. unicode-bidi: isolate;
  260. }
  261. }
  262. ol {
  263. list-style-type: decimal;
  264. display: block;
  265. list-style-type: decimal;
  266. margin-block-start: 1em;
  267. margin-block-end: 1em;
  268. margin-inline-start: 0px;
  269. margin-inline-end: 0px;
  270. padding-inline-start: 40px;
  271. unicode-bidi: isolate;
  272. }
  273. }
  274. }
  275. .custom-main{
  276. background: url('~/assets/images/swiper_bg.png') no-repeat center center;
  277. background-size: cover;
  278. width: 300px;
  279. height: 190px;
  280. }
  281. </style>